﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using lottery.admin.Models;
using lottery.admin.Data;
using Microsoft.EntityFrameworkCore;
using lottery.entity;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace lottery.admin.Controllers
{
    public class UsersController : Controller
    {
        private readonly LotteryContext _context;

        public UsersController(LotteryContext context)
        {
            _context = context;
        }

        public async Task<IActionResult> Index(string currentFilter, string searchString, string sortOrder = "create", int page = 1)
        {
            ViewData["CurrentSort"] = sortOrder;
            ViewData["PublishCountSortParm"] = sortOrder == "publish" ? "publish_desc" : "publish";
            ViewData["LotteryCountSortParm"] = sortOrder == "lottery" ? "lottery_desc" : "lottery";
            ViewData["CreateDateSortParm"] = sortOrder == "create" ? "create_desc" : "create";
            ViewData["LastLoginDateSortParm"] = sortOrder == "lastlogin" ? "lastlogin_desc" : "lastlogin";

            if (searchString != null)
            {
                page = 1;
            }
            else
            {
                searchString = currentFilter;
            }

            ViewData["CurrentFilter"] = searchString;

            var items = from d in _context.Users
                        select d;

            if (!String.IsNullOrEmpty(searchString))
            {
                items = items.Where(d => EF.Functions.ILike(d.DisplayName, $"%{searchString}%"));
            }

            switch (sortOrder)
            {
                case "publish":
                    items = items.OrderBy(d => d.PublishCount);
                    break;
                case "publish_desc":
                    items = items.OrderByDescending(d => d.PublishCount);
                    break;
                case "lottery":
                    items = items.OrderBy(d => d.LotteryCount);
                    break;
                case "lottery_desc":
                    items = items.OrderByDescending(d => d.LotteryCount);
                    break;
                case "create":
                    items = items.OrderBy(d => d.CreateDate);
                    break;
                case "create_desc":
                    items = items.OrderByDescending(d => d.CreateDate);
                    break;
                case "lastlogin":
                    items = items.OrderBy(d => d.LastLoginDate);
                    break;
                case "lastlogin_desc":
                    items = items.OrderByDescending(d => d.LastLoginDate);
                    break;
            }

            int pageSize = 10;
            PaginatedList<User> itemspage = await items.AsNoTracking().CreatePaginated(page, pageSize);

            return View(itemspage);
        }

        public async Task<IActionResult> Details(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var item = await _context.Users
                .AsNoTracking()
                .SingleOrDefaultAsync(d => d.Id == id);

            if (item == null)
            {
                return NotFound();
            }

            return View(item);
        }

        public IActionResult Create()
        {
            ViewData["StatusList"] = Status.Normal.ToSelectList(DescripByLang.Chinese);
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("DisplayName,WechartId,PublishCount,LotteryCount,Status")] User item)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    item.CreateDate = DateTime.Now;

                    _context.Add(item);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
            }
            catch (DbUpdateException ex)
            {
                //Log the error (uncomment ex variable name and write a log.)
                ModelState.AddModelError("", ex.Message);
            }
            return View(item);
        }

        public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var item = await _context.Users
                .AsNoTracking()
                .SingleOrDefaultAsync(d => d.Id == id);

            if (item == null)
            {
                return NotFound();
            }

            ViewData["StatusList"] = item.Status.ToSelectList(DescripByLang.Chinese);
            return View(item);
        }

        [HttpPost, ActionName("Edit")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> EditPost(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            var itemUpdate = await _context.Users.SingleOrDefaultAsync(d => d.Id == id);
            if (await TryUpdateModelAsync<User>(itemUpdate, "", d => d.DisplayName, d => d.Status, d => d.PublishCount, d => d.LotteryCount, d => d.WechartId))
            {
                try
                {
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
                catch (DbUpdateException /* ex */)
                {
                    //Log the error (uncomment ex variable name and write a log.)
                    ModelState.AddModelError("", "Unable to save changes. " +
                        "Try again, and if the problem persists, " +
                        "see your system administrator.");
                }
            }
            return View(itemUpdate);
        }

        public async Task<IActionResult> Delete(int? id, bool? saveChangesError = false)
        {
            if (id == null)
            {
                return NotFound();
            }

            var item = await _context.Users
                .AsNoTracking()
                .SingleOrDefaultAsync(d => d.Id == id);
            if (item == null)
            {
                return NotFound();
            }

            if (saveChangesError.GetValueOrDefault())
            {
                ViewData["ErrorMessage"] =
                    "Delete failed. Try again, and if the problem persists " +
                    "see your system administrator.";
            }

            return View(item);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var item = await _context.Users
                .AsNoTracking()
                .SingleOrDefaultAsync(d => d.Id == id);
            if (item == null)
            {
                return RedirectToAction(nameof(Index));
            }

            try
            {
                _context.Users.Remove(item);
                await _context.SaveChangesAsync();
                return RedirectToAction("Index");
            }
            catch (DbUpdateException /* ex */)
            {
                //Log the error (uncomment ex variable name and write a log.)
                return RedirectToAction(nameof(Delete), new { id, saveChangesError = true });
            }
        }
    }
}
